#! /usr/bin/env node

import {
  mkdir,
  confirm,
  copyTemplate,
  copyTemplateMulti,
  __dirname,
  renderEjsFile,
  TEMPLATE_DIR,
  write,
  cwd,
  chooseEngine,
  chooseCss,
  pathExists,
} from "./utils.js";
import { program } from "commander";
import fse from "fs-extra";
import path, { resolve } from "node:path";
import chalk from "chalk";
import { spawn } from "node:child_process";
import ora from "ora";

// console.log(resolve(__dirname(import.meta), "package.json"));
const pkg = fse.readJSONSync(resolve(__dirname(import.meta), "package.json"));

const loadTemplate = (name) => {
  // 读取 ejs 模板内容
  const contents = fse
    .readFileSync(path.resolve(TEMPLATE_DIR, `${name}.ejs`))
    .toString();
  //   模板需要的数据
  const locals = Object.create(null);
  const obj = {
    locals,
    render: function () {
      //   console.log(name + "locals >>> ", locals);
      //   console.log(contents);
      return renderEjsFile(contents, locals);
    },
  };

  return obj;
};

const main = async (name, opts) => {
  // console.log("name", name);
  // console.log("opts", opts);

  // 查询要使用模板引擎
  const engine = await chooseEngine();
  // console.log("使用的模板引擎", engine);
  // 查询要使用的 css 预编译方案
  const css = await chooseCss();
  // console.log("使用的预编译css方案", css);
  const destDirPath = path.resolve(cwd, name);
  // console.log(destDirPath);

  // 加载 app.js.ejs 模板文件
  const app = loadTemplate("js/app.js");

  // 初始化 package.json 配置
  let pkg = {
    name,
    version: "1.0.0",
    dependencies: {
      express: "~4.17.1",
      "body-parser": "~1.20.2",
    },
    scripts: {
      start: "node app.js",
    },
  };

  // 设置模板引擎依赖，默认 ejs
  switch (engine) {
    case "ejs":
      pkg.dependencies["ejs"] = "~2.6.1";
      break;
    default:
      pkg.dependencies["ejs"] = "~2.6.1";
      break;
  }

  // 初始化中间件列表
  app.locals.uses = [];
  // 初始化 app 端口号
  app.locals.port = opts.port;
  // 初始化 app 模板引擎
  app.locals.engine = engine;
  // 初始化外部依赖模块
  app.locals.modules = Object.create(null);
  // 初始化内部依赖模块 比如 Routers
  app.locals.localModules = Object.create(null);
  // Routers 挂载
  app.locals.mounts = [];

  // var bodyParser = require('body-parser')
  app.locals.modules.bodyParser = "body-parser";

  // const Index = require('./routes/index')
  // const Users = require('./routes/user')
  // 加载内部模块依赖
  app.locals.localModules.IndexoRuter = "./routes/index";
  app.locals.localModules.UsersRouter = "./routes/users";

  // 中间件添加 body-parse
  // 增加 json 和 urlencoded 的解析
  app.locals.uses.push("bodyParser.json()");
  app.locals.uses.push("bodyParser.urlencoded({ extended: false })");

  // 增加路由中间件
  app.locals.mounts.push({ path: "/", code: "IndexoRuter" });
  app.locals.mounts.push({ path: "/users", code: "UsersRouter" });

  // 目标文件夹存在 且开启了覆盖
  if (pathExists(destDirPath)) {
    if (opts.force) {
      fse.removeSync(destDirPath);
    } else {
      const r = await confirm(`${name} 文件存在确认要覆盖么`);
      if (r) {
        fse.removeSync(destDirPath);
      } else {
        process.exit(0);
      }
    }
  }

  // 创建文件
  mkdir(destDirPath);
  mkdir(destDirPath + "/public/javascripts");
  mkdir(destDirPath + "/public/images");
  mkdir(destDirPath + "/public/stylesheets");
  // 创建 views 文件夹
  mkdir(destDirPath + "/views");
  // 创建路由
  mkdir(destDirPath + "/routes");

  // 拷贝 templates 模板中的 views 文件
  copyTemplateMulti(
    path.resolve(TEMPLATE_DIR, "view"),
    path.resolve(destDirPath, "views"),
    engine
  );

  // 拷贝 templates 模板中的 样式 文件
  copyTemplateMulti(
    path.resolve(TEMPLATE_DIR, "css"),
    path.resolve(destDirPath, "public/stylesheets"),
    css
  );

  // 拷贝 templates 模板中的 routers/*js 文件
  copyTemplateMulti(
    path.resolve(TEMPLATE_DIR, "js/router"),
    path.resolve(destDirPath, "routes"),
    "js"
  );

  if (opts.git) {
    copyTemplate(
      path.resolve(TEMPLATE_DIR, "js/gitignore"),
      path.resolve(destDirPath, ".gitignore")
    );
  }

  // 创建 app.js
  write(path.resolve(destDirPath, "app.js"), app.render());
  // 创建 packages.json
  write(
    path.resolve(destDirPath, "package.json"),
    JSON.stringify(pkg, null, 2)
  );

  console.log(
    chalk.green(`           
              模板创建成功
              use: cd ${name} & npm i
              run: npm run start
    `)
  );

  const sr = await confirm("用帮你安装依赖么");
  if (sr) {
    const sp = ora("正在安装....").start();
    const c = spawn("sh", ["-c", `cd ${destDirPath} && npm i`]);
    c.on("close", () => {
      sp.stop();
      console.log(
        chalk.green(`       
                🥳🥳🥳🥳  🥳   🥳    🥳🥳
                🥳   🥳  🥳  🥳     🥳🥳
                🥳   🥳  🥳🥳       🥳🥳
                🥳   🥳  🥳  🥳     
                🥳🥳🥳🥳  🥳   🥳    🥳🥳    
        `)
      );
    });
  }
};

program
  .name("express-g")
  .description("抄的express-generator脚手架")
  .argument("[name]", "项目名称", "my-app")
  .version(pkg.version)
  .option("-p, --port [port]", "服务端口号", 3001)
  .option("-g, --git", "添加一个 .gitingore文件", false)
  .option("-f, --force", "强制覆盖非空目录", false)
  .action(main);

program.parse(process.argv);
